﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Iconator.AppCode;
using Iconator.Properties;
using McTools.Xrm.Connection;
using McTools.Xrm.Connection.WinForms;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Metadata;

namespace Iconator
{
    public sealed partial class MainForm : Form
    {
        #region Variables

        /// <summary>
        /// Crm Organization Service
        /// </summary>
        IOrganizationService _service;
        
        /// <summary>
        /// Connection statusbar
        /// </summary>
        readonly CrmConnectionStatusBar _ccsb;

        private FormHelper _formHelper;

        /// <summary>
        /// CRM 2011 Connection manager
        /// </summary>
        readonly ConnectionManager _cManager;

        private readonly List<Entity> _webResourceRetrivedList;

        private const string CodePlexProjectName = "crmiconator";

        #endregion Variables

        #region Constructor

        public MainForm()
        {
            try
            {
                InitializeComponent();

                _webResourceRetrivedList = new List<Entity>();

                Text += string.Format(" ({0})", Assembly.GetExecutingAssembly().GetName().Version);

                _cManager = new ConnectionManager();
                _cManager.ConnectionSucceed += CManagerConnectionSucceed;
                _cManager.ConnectionFailed += CManagerConnectionFailed;
                _cManager.StepChanged += CManagerStepChanged;
                _cManager.RequestPassword += CManagerRequestPassword;
                _formHelper = new FormHelper(this, _cManager);

                _ccsb = new CrmConnectionStatusBar(_cManager, _formHelper);
                Controls.Add(_ccsb);
            }
            catch (Exception error)
            {
                MessageBox.Show(this, Resources.InitializationErrorMessage + error.Message, Resources.MessageBox_Error_Title,
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion Constructor

        #region Connection methods

        bool CManagerRequestPassword(object sender, RequestPasswordEventArgs e)
        {
            return _formHelper.RequestPassword(e.ConnectionDetail);
        }

        void CManagerStepChanged(object sender, StepChangedEventArgs e)
        {
            _ccsb.SetMessage(e.CurrentStep);
        }

        void CManagerConnectionFailed(object sender, ConnectionFailedEventArgs e)
        {
            _ccsb.SetMessage("Error: " + e.FailureReason);
            MessageBox.Show(e.FailureReason, Resources.MessageBox_Error_Title, MessageBoxButtons.OK, MessageBoxIcon.Error);
            _service = null;
        }

        void CManagerConnectionSucceed(object sender, ConnectionSucceedEventArgs e)
        {
            _service = e.OrganizationService;

            _ccsb.SetConnectionStatus(true, e.ConnectionDetail);
            _ccsb.SetMessage(string.Empty);

            if (e.Parameter != null)
            {
                if(e.Parameter.ToString() == "Connect")
                {
                    DoAction();
                }
            }
        }

        #endregion Connection methods

        #region ListViewItems selection

        private void LvEntitiesSelectedIndexChanged(object sender, EventArgs e)
        {
            if (listViewEntities.SelectedItems.Count > 0)
            {
                var entity = (EntityMetadata) listViewEntities.SelectedItems[0].Tag;
                
                if (!string.IsNullOrEmpty(entity.IconSmallName))
                {
                    var queryWrSmall = from wrList in _webResourceRetrivedList
                                       where (string)wrList["name"] == entity.IconSmallName
                                       select wrList;

                    foreach (var entityWrS in queryWrSmall)
                    {
                        Image i = ImageHelper.ConvertWebResContent(entityWrS.Attributes["content"].ToString());
                        pictureBox16.Width = i.Width;
                        pictureBox16.Height = i.Height;
                        pictureBox16.Image = i;
                    }
                }
                else
                {
                    pictureBox16.Image = Resources.entity16_custom;
                }

                  if (!string.IsNullOrEmpty(entity.IconMediumName))
                {
                    var queryMedium = from wrList in _webResourceRetrivedList
                                      where (string)wrList["name"] == entity.IconMediumName
                                      select wrList;

                    foreach (var entityM in queryMedium)
                    {
                        var i = ImageHelper.ConvertWebResContent(entityM.Attributes["content"].ToString());
                        var iResize = ImageHelper.Resize(i, 32, 32);
                        pictureBox32.Width = iResize.Width;
                        pictureBox32.Height = iResize.Height;
                        pictureBox32.Image = iResize;
                    }
                }
                else
                {
                    pictureBox32.Image = Resources.ico_fhe_customentity;
                }
            }
        }

        private void LvWebRessourcesSelectedIndexChanged(object sender, EventArgs e)
        {
            if (listViewWebRessources32.SelectedItems.Count > 0)
            {
                var webRessource = (Entity)listViewWebRessources32.SelectedItems[0].Tag;
            }
        }

        private void LvWebRessourcesOtherSelectedIndexChanged(object sender, EventArgs e)
        {
            if (listViewWebRessourcesOther.SelectedItems.Count > 0)
            {
                labelSizeWr.Text = "Image size: " + 
                    ((WebResourcesManager.WebResourceAndImage) listViewWebRessourcesOther.FocusedItem.Tag).Image.Size.ToString();
            }
        }

        #endregion ListViewItems selection
       
        #region Main menu actions

        private void TsbConnectClick(object sender, EventArgs e)
        {
            if (_service == null)
            {
                _formHelper.AskForConnection("Connect");
            }
            else
            {
                DoAction();
            }
        }

        private void DoAction()
        {
            try
            {
                listViewEntities.Items.Clear();

                // Display retrieved entities
                var queryEntities = from entityList in MetadataManager.GetEntitiesList(_service)
                                    orderby entityList.DisplayName.UserLocalizedLabel.Label
                                    select entityList;

                foreach (var entity in queryEntities)
                {
                    var lvi = new ListViewItem(entity.DisplayName.UserLocalizedLabel.Label) { Tag = entity };
                    lvi.SubItems.Add(entity.LogicalName);
                    listViewEntities.Items.Add(lvi);
                }

                // Display retrieved web resources
                listViewWebRessources16.Items.Clear();
                listViewWebRessources32.Items.Clear();
                listViewWebRessourcesOther.Items.Clear();

                var queryWebResources = from webResourceList in WebResourcesManager.GetWebResourcesOnSolution(_service).Entities
                                        orderby webResourceList.Attributes["name"]
                                        select webResourceList;


                var imageList16 = new ImageList { ImageSize = new Size(16, 16), ColorDepth = ColorDepth.Depth32Bit };
                var imageList32 = new ImageList { ImageSize = new Size(32, 32), ColorDepth = ColorDepth.Depth32Bit };
                var imageListOther = new ImageList { ColorDepth = ColorDepth.Depth32Bit };

                foreach (var webResource in queryWebResources)
                {
                    var imageConverted = ImageHelper.ConvertWebResContent(webResource.Attributes["content"].ToString());

                    if (imageConverted.Size.Height == 32 && imageConverted.Size.Width == 32)
                    {
                        var lvi = new ListViewItem(webResource.Attributes["name"].ToString())
                        {
                            Tag = webResource,
                            ImageIndex = imageList32.Images.Count
                        };
                        listViewWebRessources32.Items.Add(lvi);
                        imageList32.Images.Add(imageConverted);
                    }
                    else if (imageConverted.Size.Height == 16 && imageConverted.Size.Width == 16)
                    {
                        var lvi = new ListViewItem(webResource.Attributes["name"].ToString())
                        {
                            Tag = webResource,
                            ImageIndex = imageList16.Images.Count
                        };
                        listViewWebRessources16.Items.Add(lvi);
                        imageList16.Images.Add(imageConverted);
                    }
                    else
                    {
                        var listWrImage = new WebResourcesManager.WebResourceAndImage()
                        {
                            Image = imageConverted,
                            Webresource = webResource
                        };
                        var lvi = new ListViewItem(webResource.Attributes["name"].ToString())
                        {
                            Tag = listWrImage,
                            ImageIndex = imageListOther.Images.Count,
                        };
                        listViewWebRessourcesOther.Items.Add(lvi);
                        imageListOther.Images.Add(imageConverted);
                    }
                    _webResourceRetrivedList.Add(webResource);
                }

                listViewWebRessources32.LargeImageList = imageList32;
                listViewWebRessources16.LargeImageList = imageList16;
                listViewWebRessourcesOther.LargeImageList = imageListOther;

                tsbAddIcon.Enabled = true;
                tsbApply.Enabled = true;

                SetEnableState(true);
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("Error on DoAction method : {0}", ex.InnerException.Message));
            }
        }

        private void TsbAddIconClick(object sender, EventArgs e)
        {
            var icForm = new ImageCreationForm(_service);
            icForm.StartPosition = FormStartPosition.CenterParent;
            icForm.ShowDialog();

            if (icForm.WebResourcesCreated.Count > 0)
            {
                var imageList16 = listViewWebRessources16.LargeImageList;
                var imageList32 = listViewWebRessources32.LargeImageList;
                var imageListOther = listViewWebRessourcesOther.LargeImageList;

                foreach (var webResource in icForm.WebResourcesCreated)
                {
                    var imageConverted = ImageHelper.ConvertWebResContent(webResource.Attributes["content"].ToString());

                    if (imageConverted.Size.Height == 32 && imageConverted.Size.Width == 32)
                    {
                        var lvi = new ListViewItem(webResource.Attributes["name"].ToString())
                        {
                            Tag = webResource,
                            ImageIndex = imageList32.Images.Count
                        };
                        listViewWebRessources32.Items.Add(lvi);
                        imageList32.Images.Add(imageConverted);
                    }
                    else if (imageConverted.Size.Height == 16 && imageConverted.Size.Width == 16)
                    {
                        var lvi = new ListViewItem(webResource.Attributes["name"].ToString())
                        {
                            Tag = webResource,
                            ImageIndex = imageList16.Images.Count
                        };
                        listViewWebRessources16.Items.Add(lvi);
                        imageList16.Images.Add(imageConverted);
                    }
                    else
                    {
                        var listWrImage = new WebResourcesManager.WebResourceAndImage()
                        {
                            Image = imageConverted,
                            Webresource = webResource
                        };
                        var lvi = new ListViewItem(webResource.Attributes["name"].ToString())
                        {
                            Tag = listWrImage,
                            ImageIndex = imageListOther.Images.Count,
                        };
                        listViewWebRessourcesOther.Items.Add(lvi);
                        imageListOther.Images.Add(imageConverted);
                    }
                    _webResourceRetrivedList.Add(webResource);
                }

                listViewWebRessources32.LargeImageList = imageList32;
                listViewWebRessources16.LargeImageList = imageList16;
                listViewWebRessourcesOther.LargeImageList = imageListOther;
            }
        }

        #region Apply Images to entities

        private void TsbApplyClick(object sender, EventArgs e)
        {
            if (lvMappings.Items.Count <= 0) return;

            var mappingList = (from ListViewItem item in lvMappings.Items select (EntityImageMap)item.Tag).ToList();

            var bWorker = new BackgroundWorker();
            bWorker.DoWork += BWorkerDoWork;
            bWorker.RunWorkerCompleted += BWorkerRunWorkerCompleted;
            bWorker.RunWorkerAsync(mappingList);

            lblWaiting.Text = "Applying images to entities. Please wait...";
            panelWaiting.Visible = true;
            Cursor = Cursors.WaitCursor;
            SetEnableState(false);
        }

        private void BWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            MetadataManager.ApplyImagesToEntities((List<EntityImageMap>)e.Argument, _service);
        }

        private void BWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            panelWaiting.Visible = false;
            Cursor = Cursors.Default;
            SetEnableState(true);

            if (e.Error != null)
            {
                MessageBox.Show(this, "Error while applying images to entities: " + e.Error.Message, "Error",
                               MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                lvMappings.Items.Clear();
            }
        }

        #endregion Apply Images to entities

        #region Links

        private void TsbDefineProxySettingsClick(object sender, EventArgs e)
        {
            _formHelper.EditProxySettings(this, _cManager.ConnectionsList);
        }

        private void TsbAboutClick(object sender, EventArgs e)
        {
            var aForm = new AboutForm {StartPosition = FormStartPosition.CenterParent};
            aForm.ShowDialog(this);
        }

        private void TsbRateClick(object sender, EventArgs e)
        {
            Process.Start(string.Format("http://{0}.codeplex.com/releases", CodePlexProjectName));
        }

        private void TsbDiscussClick(object sender, EventArgs e)
        {
            Process.Start(string.Format("http://{0}.codeplex.com/discussions", CodePlexProjectName));
        }

        private void TsbReportBugClick(object sender, EventArgs e)
        {
            Process.Start(string.Format("http://{0}.codeplex.com/WorkItem/Create", CodePlexProjectName));
        }

        private void TsbDonateClick(object sender, EventArgs e)
        {
            string url = "";

            string business = "tanguy92@hotmail.com";  // your paypal email
            string description = "Donation%20for%20MSCRM%20Tools%20-%20Icon%20Bulk%20Updater";            // '%20' represents a space. remember HTML!
            string country = "FR";                  // AU, US, etc.
            string currency = "EUR";                 // AUD, USD, etc.

            url += "https://www.paypal.com/cgi-bin/webscr" +
                "?cmd=" + "_donations" +
                "&business=" + business +
                "&lc=" + country +
                "&item_name=" + description +
                "&currency_code=" + currency +
                "&bn=" + "PP%2dDonationsBF";

            Process.Start(url);
        }

        #endregion Links

        #endregion

        #region Map/UnMap

        private void BtnMapClick(object sender, EventArgs e)
        {
            if (listViewEntities.SelectedItems.Count > 0 &&
                (listViewWebRessources16.SelectedItems.Count > 0 || listViewWebRessources32.SelectedItems.Count > 0 ||
                 listViewWebRessourcesOther.SelectedItems.Count > 0))
            {
                var selectedEntity = (EntityMetadata)listViewEntities.SelectedItems[0].Tag;

                var mapping = new EntityImageMap { Entity = selectedEntity };

                if (listViewWebRessources16.SelectedItems.Count > 0)
                {
                    mapping.WebResourceName = ((Entity)listViewWebRessources16.SelectedItems[0].Tag)["name"].ToString();
                    mapping.ImageSize = 16;
                }
                else if (listViewWebRessources32.SelectedItems.Count > 0)
                {
                    mapping.WebResourceName = ((Entity)listViewWebRessources32.SelectedItems[0].Tag)["name"].ToString();
                    mapping.ImageSize = 32;
                }
                else
                {
                    mapping.WebResourceName =
                        ((WebResourcesManager.WebResourceAndImage)listViewWebRessourcesOther.SelectedItems[0].Tag).Webresource["name"].ToString();

                    var issDialog = new ImageSizeSelectionDialog() { StartPosition = FormStartPosition.CenterParent };
                    if (issDialog.ShowDialog(this) == DialogResult.OK)
                    {
                        mapping.ImageSize = issDialog.ImageSizeSelected;
                    }
                    else
                    {
                        return;
                    }
                }

                var item = new ListViewItem(
                    ((EntityMetadata)listViewEntities.SelectedItems[0].Tag).DisplayName.UserLocalizedLabel.Label) { Tag = mapping };
                item.SubItems.Add(mapping.ImageSize + "x" + mapping.ImageSize);
                item.SubItems.Add(mapping.WebResourceName);

                foreach (ListViewItem existingItem in lvMappings.Items)
                {
                    if (existingItem.Text == item.Text
                        && existingItem.SubItems[1].Text == item.SubItems[1].Text)
                    {
                        MessageBox.Show(this, "There is already a mapping for this entity and this size", "Warning",
                                        MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }

                }


                lvMappings.Items.Add(item);
            }
            else
            {
                MessageBox.Show(this,"Please select at least one entity and one image", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void BtnUnmapClick(object sender, EventArgs e)
        {
            if (lvMappings.SelectedItems.Count > 0)
            {
                lvMappings.Items.Remove(lvMappings.SelectedItems[0]);
            }
        }

        private void LvWebRessourcesMouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (listViewWebRessources16.SelectedItems.Count > 0
            || listViewWebRessources32.SelectedItems.Count > 0
                || listViewWebRessourcesOther.SelectedItems.Count > 0)
            {
                BtnMapClick(null, null);
            }
        }

        #endregion

        #region Reset Icons

        private void BtnResetIconClick(object sender, EventArgs e)
        {
            if (listViewEntities.SelectedItems.Count > 0)
            {
                if (DialogResult.Yes == MessageBox.Show(this, "Are you sure you want to reset icons for this entity?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
                {
                    var bResetWorker = new BackgroundWorker();
                    bResetWorker.DoWork += BResetWorkerDoWork;
                    bResetWorker.RunWorkerCompleted += BResetWorkerRunWorkerCompleted;
                    bResetWorker.RunWorkerAsync(listViewEntities.SelectedItems[0].Tag);

                    lblWaiting.Text = "Reseting icons for entity. Please wait...";
                    panelWaiting.Visible = true;
                    Cursor = Cursors.WaitCursor;
                    SetEnableState(false);
                }
            }
            else
            {
                MessageBox.Show(this, "No entity selected", "Warning",
                              MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void BResetWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            MetadataManager.ResetIcons((EntityMetadata)e.Argument, _service);
        }

        private void BResetWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            panelWaiting.Visible = false;
            Cursor = Cursors.Default;
            SetEnableState(true);

            if (e.Error != null)
            {
                MessageBox.Show(this, "Error while reseting icons for entity: " + e.Error.Message, "Error",
                               MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                LvEntitiesSelectedIndexChanged(null, null);
            }
        }

        #endregion Reset Icons

        #region Others

        private void BtnPreviewClick(object sender, EventArgs e)
        {
            if (listViewWebRessourcesOther.FocusedItem != null)
            {
                var img =
                    ((WebResourcesManager.WebResourceAndImage)listViewWebRessourcesOther.FocusedItem.Tag).Image;

                var preview = new ImagePreview(img) { StartPosition = FormStartPosition.CenterParent };
                preview.ShowDialog();
            }
        }

        private void SetEnableState(bool enabled)
        {
            mainMenu.Enabled = enabled;
            groupBoxCurrentIcon.Enabled = enabled;
            gbEntities.Enabled = enabled;
            splitContainer1.Enabled = enabled;
        }

        private void TabControlWebResourceSelectedIndexChanged(object sender, EventArgs e)
        {
            listViewWebRessources16.SelectedItems.Clear();
            listViewWebRessources32.SelectedItems.Clear();
            listViewWebRessourcesOther.SelectedItems.Clear();
        }


        #endregion Others

        private void MainFormResize(object sender, EventArgs e)
        {
            panelWaiting.Left = Width / 2 - panelWaiting.Width / 2;
            panelWaiting.Top = Height / 2 - panelWaiting.Height / 2;
        }
    }
}
